package com.gitee.wsl.compose.ui.calendar.weekcalendar

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.layout.LayoutCoordinates
import androidx.compose.ui.layout.onPlaced
import com.gitee.wsl.compose.ui.calendar.CalendarDefaults.flingBehavior
import com.gitee.wsl.compose.ui.calendar.ItemCoordinates
import com.gitee.wsl.compose.ui.calendar.view.DaySlate
import com.gitee.wsl.compose.ui.calendar.view.ItemCoordinatesStore
import com.gitee.wsl.compose.ui.calendar.view.WeekHeaderFooterSlate
import com.gitee.wsl.serialization.time.toIso8601String


@Composable
internal fun WeekCalendarImpl(
    modifier: Modifier,
    state: WeekCalendarState,
    calendarScrollPaged: Boolean,
    userScrollEnabled: Boolean,
    reverseLayout: Boolean,
    contentPadding: PaddingValues,
    dayContent: DaySlate,
    weekHeader: WeekHeaderFooterSlate? = null,
    weekFooter: WeekHeaderFooterSlate? = null,
    onItemPlaced: (itemCoordinates: ItemCoordinates) -> Unit,
) {
    LazyRow(
        modifier = modifier,
        state = state.listState,
        flingBehavior = flingBehavior(calendarScrollPaged, state.listState),
        userScrollEnabled = userScrollEnabled,
        reverseLayout = reverseLayout,
        contentPadding = contentPadding,
    ) {
        items(
            count = state.weekIndexCount,
            key = { offset -> state.store[offset].days.first().date.toIso8601String() },
        ) { offset ->
            val week = state.store[offset]
            val currentOnItemPlaced by rememberUpdatedState(onItemPlaced)
            val itemCoordinatesStore = remember(week.days.first().date) {
                ItemCoordinatesStore(currentOnItemPlaced)
            }
            Column(
                modifier = Modifier
                    .then(
                        if (calendarScrollPaged) {
                            Modifier.fillParentMaxWidth()
                        } else {
                            Modifier.width(IntrinsicSize.Max)
                        },
                    )
                    .onPlaced(itemCoordinatesStore::onItemRootPlaced),
            ) {
                weekHeader?.invoke(this, week,state.firstDayOfWeek,state.local)
                Row {
                    week.days.forEachIndexed { column, day ->
                        Box(
                            modifier = Modifier
                                .then(if (calendarScrollPaged) Modifier.weight(1f) else Modifier)
                                .clipToBounds()
                                .onFirstDayPlaced(column, itemCoordinatesStore::onFirstDayPlaced),
                        ) {
                            dayContent(day)
                        }
                    }
                }
                weekFooter?.invoke(this, week,state.firstDayOfWeek,state.local)
            }
        }
    }
}

private fun Modifier.onFirstDayPlaced(
    column: Int,
    onFirstDayPlaced: (coordinates: LayoutCoordinates) -> Unit,
) = if (column == 0) {
    onPlaced(onFirstDayPlaced)
} else {
    this
}
